/*
 superNode.go
 Created by hupfei on 2019-08-05
*/

package v1

import (
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/pkg/errors"
	"strconv"
	"time"
	"zimuzu_cvn_web_api/config"
	"zimuzu_cvn_web_api/model"
	"zimuzu_cvn_web_api/pkg/e"
	"zimuzu_cvn_web_api/pkg/errno"
	"zimuzu_cvn_web_api/router/api"
	"zimuzu_cvn_web_api/router/api/app/middleware"
	"zimuzu_cvn_web_api/service"
)

type SuperNodeAPI struct {
}

func (a SuperNodeAPI) Name() string {
	return "Super Node API"
}

func (a SuperNodeAPI) Bind() {
	authAPI := config.C.Router.Group("/v1/app/super/user", middleware.TrackLog(), middleware.AuthMiddleware())
	{
		authAPI.GET("info", superUserInfo)
		authAPI.GET("removeMiner", removeMiner)
		authAPI.GET("incomeList", incomeList)
		authAPI.GET("incomeDetailList", incomeDetailList)
		authAPI.GET("minerList", minerList)
		authAPI.GET("superInviteCode", superInviteCode)
		//authAPI.GET("nodeCount", nodeCount)
		authAPI.GET("incomeDetail", incomeDetail)
		authAPI.GET("top", top)
		authAPI.GET("checkMiner", checkMiner)

		authAPI.GET("superNodeInfo", superNodeInfo)
		authAPI.GET("minerApplyList", minerApplyList)
		authAPI.GET("minerApplyResponse", minerApplyResponse)
		authAPI.GET("addMinerNodeNum", addMinerNodeNum)
		authAPI.GET("updateVerifyMode", updateVerifyMode)
		authAPI.GET("checkCanDelete", checkCanDelete)

		authAPI.GET("checkSecede", checkSecede)
		authAPI.POST("secede", secede)
	}

	normalAPI := config.C.Router.Group("/v1/app/super", middleware.TrackLog())
	{
		normalAPI.GET("info", superInfo)
		normalAPI.GET("startMining", startMining)
	}
}

/*
 * @ Author: hupfei
 * @ Description: 3.8.1 超级节点信息
 **/
func superInfo(c *gin.Context) {
	info, err := service.SuperInfo()
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	errno.OK.Info = "获取超级节点信息成功"
	api.SendResponse(c, errno.OK, info)
	return
}

/*
 * @ Author: hupfei
 * @ Description: 3.8.2 超级节点用户信息
 **/
func superUserInfo(c *gin.Context) {
	uid, _ := service.GetUserIdByRequest(c)

	re, err := service.SuperUserInfo(uid)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}
	errno.OK.Info = "获取超级节点用户信息成功"
	api.SendResponse(c, errno.OK, re)
	return
}

/*
 * @ Author: hupfei
 * @ Description: 3.8.5 移除旷工
 **/
type removeMinerParams struct {
	MinerId int64 `form:"minerId" binding:"required,min=1"`
	Code    int   `form:"code"`
}

func removeMiner(c *gin.Context) {
	var params removeMinerParams
	err := c.ShouldBindWith(&params, binding.Query)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	uid, _ := service.GetUserIdByRequest(c)

	userInfo, err := service.GetUserInfo(uid)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	canRemove, err := service.CheckCanDeleteMiner(uid, params.MinerId)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	if canRemove.JoinTimeCondition == 0 || canRemove.AverageIncomeCondition == 0 || canRemove.NodeNumCondition == 0 {
		if errValid := service.ValidateCode(userInfo.PhoneNumber, service.SendCodeSceneDeleteMiner, params.Code); errValid != nil {
			api.SendResponse(c, errValid, nil)
			return
		}
	}

	err = service.RemoveMiner(uid, params.MinerId, canRemove)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	errno.OK.Info = "移除成功"
	api.SendResponse(c, errno.OK, nil)
	return
}

/*
 * @ Author: hupfei
 * @ Description: 3.8.3 旷工贡献列表
 **/
func incomeList(c *gin.Context) {
	var params = model.NewDefaultPageParams()
	err := c.ShouldBindWith(&params, binding.Query)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	uid, _ := service.GetUserIdByRequest(c)
	re, err := service.IncomeList(uid, params.Page, params.Per)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}
	errno.OK.Info = "获取旷工贡献列表成功"
	api.SendResponse(c, errno.OK, re)
	return
}

/*
 * @ Author: hupfei
 * @ Description: 3.8.4 收益明细列表
 **/
func incomeDetailList(c *gin.Context) {
	var params = model.NewDefaultPageParams()
	err := c.ShouldBindWith(&params, binding.Query)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	uid, _ := service.GetUserIdByRequest(c)
	re, err := service.IncomeDetailList(uid, params.Page, params.Per)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}
	errno.OK.Info = "获取收益明细列表成功"
	api.SendResponse(c, errno.OK, re)
	return
}

/*
 * @ Author: hupfei
 * @ Description: 获取矿工列表
 **/
type minerListParams struct {
	model.PageParams
	Source int `form:"source"`
}

func minerList(c *gin.Context) {
	var params minerListParams
	params.PageParams = model.NewDefaultPageParams()
	err := c.ShouldBindWith(&params, binding.Query)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	uid, _ := service.GetUserIdByRequest(c)

	//获取超级节点信息
	node, err := model.SuperNodeInfoByUid(uid)
	if err != nil {
		api.SendResponse(c, err, nil)
	}

	re, err := model.GetMinerList(node.NodeId, params.Page, params.Per, params.Source)
	if err != nil {
		api.SendResponse(c, err, nil)
	}

	errno.OK.Info = "获取矿工列表成功"
	api.SendResponse(c, errno.OK, re)
	return
}

/*
 * @ Author: hupfei
 * @ Description: 填写超级节点邀请码
 **/
type SuperInviteCode struct {
	Code    int64 `form:"code" binding:"required"`
	NodeNum int   `form:"nodeNum" binding:"required,min=1"`
}

func superInviteCode(c *gin.Context) {
	var params SuperInviteCode
	err := c.ShouldBindQuery(&params)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}
	uid, _ := service.GetUserIdByRequest(c)

	err = service.SuperInviteCode(uid, params.Code, params.NodeNum)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	errno.OK.Info = "申请成功"
	api.SendResponse(c, errno.OK, nil)
	return
}

type StartMiningParams struct {
	MinerId int64  `form:"minerId" binding:"required"`
	Source  int    `form:"source" binding:"required"`
	T       int    `form:"t" binding:"required"`
	Sign    string `form:"sign" binding:"required"`
}

/*
 * @ Author: hupfei
 * @ Description: 开启挖矿
 **/
func startMining(c *gin.Context) {
	//var params StartMiningParams
	//err := c.ShouldBindQuery(&params)
	//if err != nil {
	//	api.SendResponse(c, errno.ParamsError, nil)
	//	return
	//}
	//
	//err = service.StartMining(params.MinerId, params.Source, params.T, params.Sign)
	//if err != nil {
	//	api.SendResponse(c, err, nil)
	//	return
	//}
	errno.OK.Info = "开启挖矿成功"
	api.SendResponse(c, errno.OK, nil)
	return
}

/*
 * @ Author: hupfei
 * @ Description: 3.8.9 节点数量
 **/
type nodeCountParams struct {
	MinerId int64 `form:"minerId" binding:"required"`
}

func nodeCount(c *gin.Context) {
	var params nodeCountParams
	err := c.ShouldBindQuery(&params)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	routerCount, _ := service.GetNodeCount(params.MinerId, 2, model.NodeTypeRouter)
	linuxCount, _ := service.GetNodeCount(params.MinerId, 2, model.NodeTypeLinux)
	pcCount, _ := service.GetNodeCount(params.MinerId, 2, model.NodeTypePc)

	re := map[string]interface{}{
		"linux":  linuxCount,
		"router": routerCount,
		"pc":     pcCount,
	}

	errno.OK.Info = "查询节点数量成功"
	api.SendResponse(c, errno.OK, re)
	return
}

/*
 * @ Author: hupfei
 * @ Description: 3.8.9 节点明细
 **/
type incomeDetailParams struct {
	MinerId int64 `form:"minerId" binding:"required"`
	Source  int   `form:"source" binding:"required"`
	model.PageParams
}

func incomeDetail(c *gin.Context) {
	var params incomeDetailParams
	params.PageParams = model.NewDefaultPageParams()
	err := c.ShouldBindQuery(&params)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	uid, _ := service.GetUserIdByRequest(c)
	//获取超级节点信息
	node, err := model.SuperNodeInfoByUid(uid)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	re, err := model.GetMinerNodeMiningList(params.MinerId, node.NodeId, params.Page, params.Per, params.Source)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}
	for k, miner := range re {
		//totalCvnt
		cvnt, _ := strconv.ParseFloat(miner.TotalCvnt, 64)
		re[k].TotalCvnt = e.CvntFormat(cvnt)

		//yesterdayCvnt
		cvnt, _ = strconv.ParseFloat(miner.YesterdayCvnt, 64)
		re[k].YesterdayCvnt = e.CvntFormat(cvnt)
	}

	errno.OK.Info = "获取节点明细成功"
	api.SendResponse(c, errno.OK, re)
	return
}

/*
 * @ Author: hupfei
 * @ Description: 3.8.10 置顶/取消置顶
 **/
type topParams struct {
	MinerId int64 `form:"minerId" binding:"required"`
	Source  int   `form:"source" binding:"required"` //1 取消置顶  2 置顶
}

func top(c *gin.Context) {
	var params topParams
	err := c.ShouldBindQuery(&params)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	updateMiner := model.MinerInfo{
		Uid:       params.MinerId,
		TopTime:   e.Int64ToInt(time.Now().Unix()),
		TopStatus: params.Source,
	}
	err = model.UpdateMinerInfo(updateMiner)
	if err != nil {
		api.SendResponse(c, errno.DbError, nil)
		return
	}
	errno.OK.Info = "已取消置顶"
	if params.Source == 2 {
		errno.OK.Info = "已置顶"
	}
	api.SendResponse(c, errno.OK, nil)
	return
}

//检查矿工身份
//Auth:Xu
func checkMiner(c *gin.Context) {
	uid, _ := service.GetUserIdByRequest(c)
	minerInfo, err := service.GetMinerInfo(uid)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}
	var res int
	if minerInfo.Uid != 0 {
		res = 2
	} else {
		res = 1
	}
	data := make(map[string]interface{})
	data["res"] = res

	errno.OK.Info = "ok"
	api.SendResponse(c, errno.OK, data)
	return
}

/*
 * @ Author: hupfei
 * @ Description: 超级节点基本信息
 **/
type superNodeInfoParams struct {
	SuperUid int64 `form:"superUid" binding:"required"`
}

func superNodeInfo(c *gin.Context) {
	var params superNodeInfoParams
	err := c.ShouldBindQuery(&params)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	info, err := model.SuperNodeInfoByUid(params.SuperUid)
	if err != nil {
		api.SendResponse(c, errno.DbSearchError, nil)
		return
	}

	pledgedNodeNum, err := model.GetSuperNodePledgedNodeNum(info.NodeId)
	if err != nil {
		api.SendResponse(c, errno.DbSearchError, nil)
		return
	}

	errno.OK.Info = "ok"
	api.SendResponse(c, errno.OK, map[string]interface{}{
		"name":         info.Name,
		"remainingNum": info.MaxNodeNum - pledgedNodeNum,
	})
	return
}

/*
 * @ Author: hupfei
 * @ Description: 矿工审核列表
 **/
func minerApplyList(c *gin.Context) {
	var params = model.NewDefaultPageParams()
	err := c.ShouldBindWith(&params, binding.Query)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	uid, _ := service.GetUserIdByRequest(c)
	list, err := model.GetMinerApplyList(uid, params.Page, params.Per)
	if err != nil {
		api.SendResponse(c, errno.DbSearchError, nil)
		return
	}

	errno.OK.Info = "ok"
	api.SendResponse(c, errno.OK, list)
	return
}

/*
 * @ Author: hupfei
 * @ Description: 超级节点审核
 **/
type minerApplyResponseParams struct {
	Source   int   `form:"source" binding:"required"` //1 通过  2 拒绝
	MinerUid int64 `form:"minerUid" binding:"required"`
}

func minerApplyResponse(c *gin.Context) {
	var params minerApplyResponseParams
	err := c.ShouldBindWith(&params, binding.Query)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	uid, _ := service.GetUserIdByRequest(c)
	err = service.ApplyResponse(uid, params.MinerUid, params.Source)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	errno.OK.Info = "ok"
	api.SendResponse(c, errno.OK, nil)
	return
}

/*
 * @ Author: hupfei
 * @ Description: 增加矿工可开设的节点数
 **/
type addMinerNodeNumParams struct {
	Num      int   `form:"num" binding:"required,min=1"`
	MinerUid int64 `form:"minerUid" binding:"required"`
}

func addMinerNodeNum(c *gin.Context) {
	var params addMinerNodeNumParams
	err := c.ShouldBindWith(&params, binding.Query)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	uid, _ := service.GetUserIdByRequest(c)
	superNode, err := model.SuperNodeInfoByUid(uid)
	if err != nil {
		api.SendResponse(c, errno.DbSearchError, nil)
		return
	}

	miner, err := model.GetMinerInfoByUid(params.MinerUid)
	if err != nil {
		api.SendResponse(c, errno.DbSearchError, nil)
		return
	}

	if params.Num+miner.MaxNodeNum > superNode.MaxNodeNum {
		api.SendResponse(c, errors.New("您的挖矿名额不足"), nil)
		return
	}

	err = model.UpdateMinerMaxNodeNum(params.MinerUid, superNode.NodeId, params.Num)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	errno.OK.Info = "ok"
	api.SendResponse(c, errno.OK, nil)
	return
}

/*
 * @ Author: hupfei
 * @ Description: 超级节点修改审核模式
 **/
type updateVerifyModeParams struct {
	Status int `form:"status" binding:"required"` //1-需审核后加入，2-禁止任何人加入
}

func updateVerifyMode(c *gin.Context) {
	var params updateVerifyModeParams
	err := c.ShouldBindWith(&params, binding.Query)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	uid, _ := service.GetUserIdByRequest(c)
	err = model.UpdateVerifyMode(uid, params.Status)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}
	errno.OK.Info = "ok"
	api.SendResponse(c, errno.OK, nil)
	return
}

/*
 * @ Author: hupfei
 * @ Description: 检查是否满足删除条件
 **/
type checkCanDeleteParams struct {
	MinerUid int64 `form:"minerUid" binding:"required,min=1"`
}

func checkCanDelete(c *gin.Context) {
	var params checkCanDeleteParams
	err := c.ShouldBindWith(&params, binding.Query)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	uid, _ := service.GetUserIdByRequest(c)
	res, err := service.CheckCanDeleteMiner(uid, params.MinerUid)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}
	errno.OK.Info = "ok"
	api.SendResponse(c, errno.OK, res)
	return
}

//检查是否满足退出条件
//Author: TXG
func checkSecede(c *gin.Context) {
	uid, _ := service.GetUserIdByRequest(c)
	data, err := service.CheckSecede(uid)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}
	errno.OK.Info = "ok"
	api.SendResponse(c, errno.OK, data)
	return
}

//退出超级节点
//Author: TXG
func secede(c *gin.Context) {
	var (
		postData model.SecedeSuperNode
	)
	//获取post参数
	if err := c.ShouldBindWith(&postData, binding.FormPost); err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}
	uid, _ := service.GetUserIdByRequest(c)
	err := service.Secede(uid, postData)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}
	errno.OK.Info = "ok"
	api.SendResponse(c, errno.OK, nil)
	return
}
